/**
 * Copyright (C) 2010  Johan Basson
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package symorg.midlet;

import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
import symorg.io.FileSelector;
import symorg.io.OrgFile;
import symorg.util.Node;

/**
 * @author johan
 */
public class SymOrgMidlet extends MIDlet implements CommandListener {

    private Display display;
    private OrgFile file;
    private Object data;
    private Stack outlineNav;
    private int currentNavPos = -1;
    private String selectedFile;
    private int fromScreen = 0;
    private static int OUTLINE_SCREEN = 1;
    private static int TODO_SCREEN = 2;
    private static Command EXIT = new Command("Exit", Command.EXIT, 1);
    private static Command BACK = new Command("Back", Command.BACK, 1);
  //  private static Command EDIT = new Command("Edit", Command.OK, 1);
    private static Command OPEN = new Command("Open", Command.ITEM, 1);
    private static Command TODO = new Command("Todo", Command.OK, 1);
    private static Command OUTLINE = new Command("Outline", Command.OK, 1);
    private static Command LOAD = new Command("Load", Command.OK, 1);

    public void startApp() {
        outlineNav = new Stack();
        display = Display.getDisplay(this);

        try {
            // String[] roots = General.getRoots();
            //  log = new Logger("file:///" + roots[0] + "/symorg.log");

            mainScreen();

        } catch (Exception ex) {
            ex.printStackTrace();
            //  if (log != null) {
            //      log.error("startApp", ex);
            // }
            showError("startApp", ex.getMessage());

        }
    }

    public void showError(String origin, String message) {
        Form form = new Form("Error");
        form.append(origin);
        form.append(" : ");
        form.append(message);
        form.setCommandListener(this);
        form.addCommand(EXIT);
        display.setCurrent(form);
    }

    public void error(String message) {
        Form form = new Form("Error");
        form.append(message);
        form.addCommand(BACK);
        display.setCurrent(form);
    }

    /**
     * Sets the selected file
     * @param file
     */
    public void setSelectedFile(String file) {
        this.selectedFile = file;
    }

    /**
     * Midlet display
     * @return
     */
    public Display getDisplay() {
        return display;
    }

    /**
     * Load Org File
     */
    public void loadOrgFile() {
        InputStream in = null;
        try {
            FileConnection con = (FileConnection) Connector.open("file:///" + selectedFile);

            if (con.isDirectory()) {
                error("Cannot open directory");
            } else {
                in = Connector.openInputStream("file:///" + selectedFile);
                file = new OrgFile(in);
            }

        } catch (IOException ex) {
            // log.error("loadOrgFile : IOException ", ex);
            showError("loadOrgFile (IOE) [" + "file:///" + selectedFile + "]", ex.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {

                // log.error("loadOrgFile : close", ex);
                showError("loadOrfFile (finally) ", ex.getMessage() + " " + "file:///" + selectedFile);
            }
        }
    }

    /**
     * Main screen
     */
    public void mainScreen() {
        Form form = new Form("Welcome");
        form.setCommandListener(this);
        form.addCommand(LOAD);
        form.addCommand(EXIT);
        getDisplay().setCurrent(form);
    }

    /**
     * Show todo list
     */
    public void listTodo() {

        if (file == null) {
            loadOrgFile();
        }

        try {
            Image icon = Image.createImage("/symorg/images/todo.png");
            Vector items = file.findTodo();
            String[] lines = new String[items.size()];
            Image[] imageArray = new Image[items.size()];
            for (int t = 0; t < items.size(); t++) {
                Node node = (Node) items.elementAt(t);
                lines[t] = node.headline;
                imageArray[t] = icon;
            }
            List list = new List("Todo", Choice.IMPLICIT, lines, imageArray);
            display.setCurrent(list);
            list.setCommandListener(this);

            list.addCommand(OUTLINE);
            list.addCommand(LOAD);
            list.addCommand(EXIT);

            fromScreen = TODO_SCREEN;
        } catch (IOException ex) {
            //log.error("listTodo : Open Image", ex);
            ex.printStackTrace();
            showError("listTodo", ex.getMessage());
        }
    }

    /**
     * Show outline
     */
    public void outline(int nodeId) {

        Vector items = null;

        if (file == null) {
            loadOrgFile();
        }

        currentNavPos = nodeId;

        if (nodeId == -1) {
            items = file.findLevel1Nodes();
        } else {
            items = file.findChildNodes(nodeId);
        }

        if (items.size() > 0) {                 // There is children

            try {
                // There is children
                Image noteIcon = Image.createImage("/symorg/images/note.png");
                Image folderIcon = Image.createImage("/symorg/images/folder.png");

                int[] lookup = new int[items.size()];
                String[] lines = new String[items.size()];
                Image[] imageArray = new Image[items.size()];

                for (int t = 0; t < items.size(); t++) {
                    Node node = (Node) items.elementAt(t);
                    lookup[t] = node.id;
                    lines[t] = node.headline;

                    if (file.isLeaf(node.id)) {
                        imageArray[t] = noteIcon;
                    } else {
                        imageArray[t] = folderIcon;
                    }
                }

                data = lookup;

                List list = new List("Outline", Choice.IMPLICIT, lines, imageArray);
                list.setCommandListener(this);
                list.addCommand(EXIT);
                if (nodeId != -1) {
                    list.addCommand(BACK);
                }
//                list.addCommand(EDIT);
                list.addCommand(TODO);
                list.addCommand(OPEN);
                list.addCommand(LOAD);


                display.setCurrent(list);

                fromScreen = OUTLINE_SCREEN;
            } catch (IOException ex) {
                ex.printStackTrace();
                //log.error("outline : load image", ex);
                showError("outline", ex.getMessage());
            }

        } else {                            // Display Note
            showNoteText(nodeId);
        }
    }

    private void showNoteText(int nodeId) {
        Node node = file.getNodeById(nodeId);
        if (node == null) {
            display.setCurrent(new Alert("Node " + nodeId + " could not be located"));
        } else {
            Form form = new Form(node.headline);
            form.append(node.body);
            form.setCommandListener(this);
            form.addCommand(EXIT);
//            form.addCommand(EDIT);
            form.addCommand(BACK);
            display.setCurrent(form);
        }
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable d) {

        /* Exit */
        if (c == EXIT) {
            destroyApp(false);
            notifyDestroyed();
        }

        /* Open */
        if (c == OPEN) {
            showSelectedNote(d);
        }

        /* Load org file */
        if (c == LOAD) {
            doFileSelection();
        }

        /* Show todo */
        if (c == TODO) {
            listTodo();
        }

        /* Show outline */
        if (c == OUTLINE) {
            outline(-1);
        }

        /* Back */
        if (c == BACK) {
            if (d instanceof List) {
                //TODO check if display is outline
                Integer prev = (Integer) outlineNav.pop();
                outline(prev.intValue());
            } else {
                doFileSelection();
            }
        }
    }

    /**
     * Show Next Note
     * 
     * @param d
     */
    private void showSelectedNote(Displayable d) {
        //TODO check if display is outline
        outlineNav.push(new Integer(currentNavPos));
        int lookup[] = (int[]) data;
        outline(lookup[((List) d).getSelectedIndex()]);
    }

    /**
     * Show file selection
     */
    private void doFileSelection() {
        try {
            FileSelector fs = new FileSelector(this, new Form("Select org file"));
            fs.show();
        } catch (Exception ex) {
            ex.printStackTrace();
            //  log.error("Open file ", ex);
            showError("Load", ex.getMessage());
        }
    }
}
